package erik.ds.btree;

class BinaryNode<T> {
	public BinaryNode() {
		this(null, null, null);
	}

	public BinaryNode(T theElement, BinaryNode<T> lt, BinaryNode<T> rt) {
		element = theElement;
		left = lt;
		right = rt;
	}
	/**
	 * Return a reference to a node that is the root of a duplicate of the binary
	 * tree rooted at the current node.
	 */
	public BinaryNode<T> duplicate() {
		BinaryNode<T> root = new BinaryNode<T>(element, null, null);
		
		if (left != null)
			root.left = left.duplicate();
		if (right != null) 
			root.right = right.duplicate();
		return root;
	}
	
	/**
	 * Return the size of the binary tree rooted at t.
	 * @param t
	 * @return
	 */
	public static <T> int size(BinaryNode<T> t) {
		if (t == null)
			return 0;
		else
			return 1 + size(t.left) + size(t.right);
	}
	
	/**
	 * Return the height of the binary tree rooted at t.
	 * @param t
	 * @return
	 */
	public static <T> int height(BinaryNode<T> t) {
		if (t == null)
			return -1;
		else
			return 1 + Math.max(height(t.left), height(t.right));
	}
	
	/**
	 * Print tree rooted at current node using pre-order traversal;
	 */
	public void printPreOrder() {
		System.out.println(element);
		if (left != null)
			left.printPreOrder();
		if (right != null)
			right.printPreOrder();
	}
	
	/**
	 * Print tree rooted at current node using post-order traversal;
	 */
	public void printPostOrder() {
		if (left != null)
			left.printPostOrder();
		if (right != null)
			right.printPostOrder();
		System.out.println(element);
	}
	
	/**
	 * Print tree rooted at current node using in-order traversal;
	 */
	public void printInOrder() {
		if (left != null)
			left.printInOrder();
		System.out.println(element);
		if (right != null)
			right.printInOrder();
	}
	
	public T getElement() {
		return element;
	}

	public void setElement(T element) {
		this.element = element;
	}

	public BinaryNode<T> getLeft() {
		return left;
	}

	public void setLeft(BinaryNode<T> left) {
		this.left = left;
	}

	public BinaryNode<T> getRight() {
		return right;
	}

	public void setRight(BinaryNode<T> right) {
		this.right = right;
	}

	private T element;
	private BinaryNode<T> left;
	private BinaryNode<T> right;
}
